home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
forth
/
amiga
/
amigaker.arc
/
03.math
< prev
next >
Wrap
Text File
|
1987-12-30
|
26KB
|
717 lines
;
; 03.arithmatic
;
; 32 and double (64) bit arithmatics. The double arithmatic is ment to
; be used as an internal to retain greater precision.
;
; comparisons to zero and comparisons between two numbers.
;
; double stack operations
mulusub moveq #0,d4 ;add d0 * 2^16 to
moveq #0,d5 ; double d2 d3 (d3=high)
move.w d0,d4
swap d4 ;first shift d0 16 times
swap d0 ;then add to double in d2/3
move.w d0,d5
add.l d4,d2
addx.l d5,d3
rts
* um* (s n1 n2 -- d ) return double result of n1 times n2
dc.w -1
dc.l link1
link1 set *-4
dc.b $83,'um',$80!'*'
cnop 0,2
_um_times dc.l *+4
movem.l (sp),d0-d1 ;if both are word sized
moveq #0,d2 ; use hardware multiply
move.w #$FFFF,d2
cmp.l d2,d0 ;if d0>ffff jump to long
bhi.s 1$ ; routine
cmp.l d2,d1 ;or if d1 > ffff
bhi.s 1$
mulu d0,d1 ;hardware multiply
moveq #0,d0
movem.l d0-d1,(sp)
jmp (a3)
; a.b X c.d = bxd
1$ moveq #0,d2 ; cxb
moveq #0,d3 ; axd
move.w 2(sp),d0 ; axc
move.w 6(sp),d1 ; -------
mulu d1,d0 ; d3 | d2
move.l d0,d2
move.w 2(sp),d0 ; long way to multiply two
move.w 4(sp),d1 ; 32bit numbers.
mulu d1,d0
bsr mulusub
move.w (sp),d0
move.w 6(sp),d1
mulu d1,d0
bsr mulusub
move.w (sp),d0
move.w 4(sp),d1
mulu d1,d0
add.l d0,d3
move.l d2,4(sp)
move.l d3,(sp)
jmp (a3)
* u*d
dc.w -1
dc.l link1
link1 set *-4
dc.b $83,'u*',$80!'d'
cnop 0,2
_u_times_d dc.l nest,_um_times,_exit
* um/mod (s d n -- remainder d#quotient ) double divided by single
dc.w -1
dc.l link1 ; tries to be efficient
link1 set *-4
dc.b $86,'um/mo',$80!'d'
cnop 0,2
_um_divide_mod dc.l *+4
move.l (sp)+,d0 ;d0 = b
move.l (sp)+,d3 ;d3 = a(h)
move.l (sp)+,d2 ;d2 = a(l)
moveq #0,d1
move.w #$FFFF,d1 ;d1 holds mask for word test
tst.l d0
bne.s 1$ ; if b=0 return an error
move.l d0,-(sp)
dc.w $4878,$FFFF ;pea -1
dc.w $4878,$FFFF ; return a double
jmp (a3)
1$
tst.l d3 ;check for a(h)=0
bne.s um_divide_mod ; if not do long division
cmp.l d1,d0 ;is b a word?
bls.s 2$ ; if so, do hardware div.
cmp.l d0,d2 ;if a(l) >= b
bcc.s um_divide_mod ; do long division.
move.l d2,-(sp) ; return a(l) as remainder
pea 0 ; and zero as result
pea 0
jmp (a3)
2$ ;here if b=word
cmp.l d1,d2 ;must check a(l) for long/word
bls.s 3$ ;if word divide once
swap d2 ;move a(l)highword
move.w d2,d3 ; d3 (ah) was 0
divu d0,d3
move.w d3,d1 ;save Q(h),
swap d1 ; set into high bits
swap d2 ; next do a(l)lowword
3$
move.w d2,d3 ;move lowword
divu d0,d3
move.w d3,d1 ;save Q(l)
clr.w d3 ; zero upper bits of remainder
swap d3
move.l d3,-(sp) ;push remainder
move.l d1,-(sp) ;push quotient
pea 0 ; and a double quotient
jmp (a3)
um_divide_mod moveq #0,d6 ; b - d1 d0
moveq #0,d7 ; a - d3 d2
moveq #0,d1 ; a'- d5 d4
; Sc (sp)
; result d7 d6
; Sa a0
move.w d6,-(sp) ;zero Sc
move.l d6,a0 ; and Sa
tst.l d3 ; its possible for a=neg
bmi.s 4$
1$ addq.w #1,a0 ; shift a left until neg.
subq.w #1,(sp) increment Sa, decr. Sc
lsl.l #1,d2
roxl.l #1,d3
bpl.s 1$
4$ lsr.l #1,d3 ;adjust so highest bit is 0
roxr.l #1,d2
roxr.l #1,d7 ; ** but save bit in d7
subq.w #1,a0
addq.w #1,(sp)
2$ move.l d2,d4 ; Save a in a'
move.l d3,d5
3$ addq #1,(sp) ; shift b left until neg.
lsl.l #1,d0 ; increment Sc
roxl.l #1,d1
bpl.s 3$
lsr.l #1,d1 ;adjust so highest bit is 0
roxr.l #1,d0
subq.w #1,(sp)
bmi.s 9$ ; do not divide
5$ sub.l d0,d2
subx.l d1,d3 ; a = a - b
eori #%10000,ccr ; flip x bit
bcs.s 6$
move.l d2,d4 ;subtract was ok, a' <- a
move.l d3,d5
bra.s 8$
6$ move.l d4,d2 ;restore a
move.l d5,d3
8$ roxl.l #1,d6 ;shift x into result
roxl.l #1,d7
roxl.l #1,d2 ; a = a * 2 using d7 bits
roxl.l #1,d3
addq.w #1,a0 ; increment Sa
subq.w #1,(sp) ;decrement Sc
bmi.s 7$ ; exit if minus
move.l d2,d4 ; a' = a
move.l d3,d5
bra.s 5$
7$ subq.w #1,a0 ; adjust Sa
9$ move.w a0,d0 ;get Sa
bra.s 11$
10$ lsr.l #1,d5 ; shift a' right Sa times
roxr.l #1,d4
11$ dbra d0,10$
tst.w (sp)+ ;drop Sc
move.l d4,-(sp) ;push remainder
move.l d6,-(sp) ;push result low
move.l d7,-(sp) ;push result high
jmp (a3)
* 0< (s n -- f ) return true if n is negative
dc.w -1
dc.l link0
link0 set *-4
dc.b $82,'0',$80!'<'
cnop 0,2
_0_less dc.l *+4
tst.l (sp)
bmi.s yes
bra.s no
* 0= (s n -- f ) return true if tos is 0
dc.w -1
dc.l link0
link0 set *-4
dc.b $82,'0',$80!'='
cnop 0,2
_0_equal dc.l *+4
tst.l (sp)
beq.s yes
bra.s no
* 0> (s n -- f ) return true if tos is positive
dc.w -1
dc.l link0
link0 set *-4
dc.b $82,'0',$80!'>'
cnop 0,2
_0_greater dc.l *+4
tst.l (sp)
bgt.s yes
bra.s no
* 0<> (s n -- f ) return true if tos is not 0
dc.w -1
dc.l link0
link0 set *-4
dc.b $83,'0<',$80!'>'
cnop 0,2
_0_notequal dc.l *+4
tst.l (sp)
bne.s yes
bra.s no
yes move.l #-1,(sp) ;label - yes
jmp (a3)
no clr.l (sp) ;label - no
jmp (a3)
* < (s n1 n2 -- f ) true if n1 < n2
dc.w -1
dc.l link0
link0 set *-4
dc.b $81,$80!'<'
cnop 0,2
_less_than dc.l *+4
move.l (sp)+,d0
cmp.l (sp),d0
bgt.s yes
bra.s no
* = (s n1 n2 -- f ) true if n1=n2
dc.w -1
dc.l link1
link1 set *-4
dc.b $81,$80!'='
cnop 0,2
_equals dc.l *+4
move.l (sp)+,d0
cmp.l (sp),d0
beq.s yes
bra.s no
* > (s n1 n2 -- f ) true if n1>n2
dc.w -1
dc.l link2
link2 set *-4
dc.b $81,$80!'>'
cnop 0,2
_greater_than dc.l *+4
move.l (sp)+,d0
cmp.l (sp),d0
blt.s yes
bra.s no
* <> (s n1 n2 -- f ) true if n1<>n2
dc.w -1
dc.l link0
link0 set *-4
dc.b $82,'<',$80!'>'
cnop 0,2
_not_equals dc.l *+4
move.l (sp)+,d0
cmp.l (sp),d0
bne.s yes
bra.s no
* ?negate (s n1 n2 -- n1 ) negate n1 if n2 is negative
dc.w -1
dc.l link3
link3 set *-4
dc.b $87,'?negat',$80!'e'
cnop 0,2
_question_negate dc.l *+4
move.l (sp)+,d0
bpl.s 1$
neg.l (sp)
1$ jmp (a3)
* u< (s n1 n2 -- f ) true if unsigned n1<n2
dc.w -1
dc.l link1
link1 set *-4
dc.b $82,'u',$80!'<'
cnop 0,2
_u_less dc.l *+4
move.l (sp)+,d0
cmp.l (sp),d0
bhi yes
bra no
* u> (s n1 n2 -- f ) true if unsigned n1>n2
dc.w -1
dc.l link1
link1 set *-4
dc.b $82,'u',$80!'>'
cnop 0,2
_u_greater dc.l *+4
move.l (sp)+,d0
cmp.l (sp),d0
bcs yes
bra no
* min (s n1 n2 -- n3 ) return minimun of n1, n2
dc.w -1
dc.l link1
link1 set *-4
dc.b $83,'mi',$80!'n'
cnop 0,2
_min dc.l *+4
move.l (sp)+,d0
cmp.l (sp),d0
bgt.s 1$
move.l d0,(sp)
1$ jmp (a3)
* max (s n1 n2 -- n3 ) return maximum of n1, n2
dc.w -1
dc.l link1
link1 set *-4
dc.b $83,'ma',$80!'x'
cnop 0,2
_max dc.l *+4
move.l (sp)+,d0
cmp.l (sp),d0
blt.s 1$
move.l d0,(sp)
1$ jmp (a3)
* between (s n min max -- f ) true if min <= n <= max
dc.w -1
dc.l link2
link2 set *-4
dc.b $87,'betwee',$80!'n'
cnop 0,2
_between dc.l *+4
move.l (sp)+,d0
move.l (sp)+,d1
move.l (sp),d2
cmp.l d2,d1
bgt no
cmp.l d2,d0
blt no
bra yes
* within (s n min max -- f ) true if min <= n < max
dc.w -1
dc.l link3
link3 set *-4
dc.b $86,'withi',$80!'n'
cnop 0,2
_within dc.l *+4
subq.l #1,(sp)
bra _between+4
* 2@ (s addr -- d ) get double from address
dc.w -1
dc.l link2 ; in memory addr - high
link2 set *-4 ; addr+4 low
dc.b $82,'2',$80!'@' ; on stack 2nd low
cnop 0,2 ; tos high
_2_fetch dc.l *+4
move.l (sp),a0
move.l 4(a0),(sp)
move.l (a0),-(sp)
jmp (a3)
* 2! (s d addr -- ) store d at address
dc.w -1
dc.l link2
link2 set *-4
dc.b $82,'2',$80!'!'
cnop 0,2
_2_store dc.l *+4
move.l (sp)+,a0
move.l (sp)+,(a0)+
move.l (sp)+,(a0)
jmp (a3)
* 2drop (s d -- ) drop double from tos
dc.w -1
dc.l link2
link2 set *-4
dc.b $85,'2dro',$80!'p'
cnop 0,2
_2drop dc.l *+4
addq.l #8,sp
jmp (a3)
* 2dup (s d1 -- d1 d1 ) duplicate double
dc.w -1
dc.l link2
link2 set *-4
dc.b $84,'2du',$80!'p'
cnop 0,2
_2dup dc.l *+4
move.l 4(sp),-(sp)
move.l 4(sp),-(sp)
jmp (a3)
* 2swap (s d1 d2 -- d2 d1 ) swap top two doubles on the stack
dc.w -1
dc.l link2
link2 set *-4
dc.b $85,'2swa',$80!'p'
cnop 0,2
_2swap dc.l *+4
movem.l (sp)+,d0-d3
exg d0,d2
exg d1,d3
movem.l d0-d3,-(sp)
jmp (a3)
* 2over (s d1 d2 -- d1 d2 d1 ) copy second double
dc.w -1
dc.l link2
link2 set *-4
dc.b $85,'2ove',$80!'r'
cnop 0,2
_2over dc.l *+4
move.l 12(sp),-(sp)
move.l 12(sp),-(sp)
jmp (a3)
* 3dup (s a b c -- a b c a b c ) duplicate 3 top elements
dc.w -1
dc.l link3
link3 set *-4
dc.b $84,'3du',$80!'p'
cnop 0,2
_3dup dc.l *+4
lea 12(sp),a0
move.l -(a0),-(sp)
move.l -(a0),-(sp)
move.l -(a0),-(sp)
jmp (a3)
* w>s (s w -- n ) extend word to single
dc.w -1
dc.l link3
link3 set *-4
dc.b $83,'w',$3E,$80!'s'
cnop 0,2
_w_to_s dc.l *+4
move.l (sp),d0
ext.l d0
move.l d0,(sp)
jmp (a3)
* d+ (s d1 d2 -- dsum ) add two double numbers
dc.w -1
dc.l link0
link0 set *-4
dc.b $82,'d',$80!'+'
cnop 0,2
_d_plus dc.l *+4
move.l (sp)+,d1
move.l (sp)+,d0
move.l (sp)+,d2
add.l d0,(sp)
addx.l d2,d1
move.l d1,-(sp)
jmp (a3)
* dnegate (s d -- d ) negate double number on the stack
dc.w -1
dc.l link0
link0 set *-4
dc.b $87,'dnegat',$80!'e'
cnop 0,2
_dnegate dc.l *+4
neg.l 4(sp)
negx.l (sp)
jmp (a3)
* s>d (s n -- d ) extend single to a double
dc.w -1
dc.l link3
link3 set *-4
dc.b $83,'s',$3e,$80!'d'
cnop 0,2
_s_to_d dc.l *+4
moveq #0,d0
tst.l (sp)
bpl.s 1$
subq.l #1,d0
1$ move.l d0,-(sp)
jmp (a3)
* dabs (s d -- |d| ) return absolute double
dc.w -1
dc.l link0
link0 set *-4
dc.b $84,'dab',$80!'s'
cnop 0,2
_dabs dc.l *+4
tst.l (sp)
bmi _dnegate+4
jmp (a3)
* d2* (s d -- d*2 ) 64 bit left shift
dc.w -1
dc.l link0
link0 set *-4
dc.b $83,'d2',$80!'*'
cnop 0,2
_d2_times dc.l *+4
move.l (sp)+,d1
move.l (sp),d0
lsl.l #1,d0
roxl.l #1,d1
move.l d0,(sp)
move.l d1,-(sp)
jmp (a3)
* d2/ (s d -- d/2 ) 64 bit arithmatic right shift
dc.w -1
dc.l link0
link0 set *-4
dc.b $83,'d2',$80!'/'
cnop 0,2
_d2_divide dc.l *+4
move.l (sp)+,d1
move.l (sp),d0
asr.l #1,d0
roxr.l #1,d1
move.l d0,(sp)
move.l d1,-(sp)
jmp (a3)
* d- (s d1 d2 -- d3 ) subtract d2 from d1
dc.w -1
dc.l link0
link0 set *-4
dc.b $82,'d',$80!'-'
cnop 0,2
_d_minus dc.l *+4
move.l (sp)+,d1
move.l (sp)+,d0
move.l (sp)+,d3
sub.l d0,(sp)
subx.l d1,d3
move.l d3,-(sp)
jmp (a3)
* ?dnegate (s d n -- d ) negate double if n is negative
dc.w -1
dc.l link3
link3 set *-4
dc.b $88,'?dnegat',$80!'e'
cnop 0,2
_question_dnegate dc.l *+4
tst.l (sp)+
bmi _dnegate+4
jmp (a3)
* d= (s d1 d2 -- f ) true if d1=d2
dc.w -1
dc.l link0
link0 set *-4
dc.b $82,'d',$80!'='
cnop 0,2
_d_equals dc.l *+4
move.l (sp)+,d0
move.l (sp)+,d2
move.l (sp)+,d1
move.l (sp),d3
cmp.l d0,d1
bne no
cmp.l d2,d3
bne no
bra yes
* *d (s n1 n2 -- d ) multiply two singles to a double
dc.w -1
dc.l link2
link2 set *-4
dc.b $82,'*',$80!'d'
cnop 0,2
_times_d dc.l *+4
move.l (sp)+,d0
move.l (sp)+,d1
move.l d0,d2
eor.l d1,d2
move.l d2,-(rp)
move.l d1,-(sp)
bpl.s 1$
neg.l (sp)
1$ move.l d0,-(sp)
bpl.s 2$
neg.l (sp)
2$ lea _um_times,w
jsr callword
move.l (rp)+,-(sp)
bra _question_dnegate+4
* m/mod (s d n -- rem quot ) floored division.
dc.w -1
dc.l link1
link1 set *-4
dc.b $85,'m/mo',$80!'d'
cnop 0,2
_m_divide_mod dc.l *+4
move.l (sp)+,d0 ; ?dup if ... then ;
beq.s 5$
move.l d0,-(rp) ; dup >r
move.l (sp),d1
eor.l d0,d1 ; 2dup xor >r
move.l d1,-(rp)
move.l d0,-(rp) ; >r
tst.l (sp)
bpl.s 1$ ; dabs
neg.l 4(sp)
negx.l (sp)
1$ move.l (rp),-(sp) ; r@
bpl.s 2$
neg.l (sp) ; abs
2$ lea _um_divide_mod,w
jsr callword
addq.l #4,sp ; drop
move.l (rp)+,d0 ; swap r> ?negate swap
bpl.s 3$
neg.l 4(sp)
3$ move.l (rp)+,d0 ; r> 0< if
bpl.s 4$
neg.l (sp)
tst.l 4(sp)
beq.s 4$
subq.l #1,(sp)
move.l (rp),d0
sub.l 4(sp),d0
move.l d0,4(sp)
4$ tst.l (rp)+
5$ jmp (a3)
* * (s n1 n2 -- n3 ) 32 multiplication
dc.w -1
dc.l link2
link2 set *-4
dc.b $81,$80!'*'
cnop 0,2
_times dc.l nest
dc.l _um_times,_drop
dc.l _exit
* /mod ( n1 n2 -- rem quot )
dc.w -1
dc.l link3
link3 set *-4
dc.b $84,'/mo',$80!'d'
cnop 0,2
_divide_mod dc.l *+4
moveq #0,d0
move.l (sp)+,d1
tst.l (sp)
bpl.s 1$
neg.l d0
1$ move.l d0,-(sp)
move.l d1,-(sp)
bra _m_divide_mod+4
* / (s n1 n2 -- n3 ) return n1/n2
dc.w -1
dc.l link3
link3 set *-4
dc.b $81,$80!'/'
cnop 0,2
_divide dc.l nest
dc.l _divide_mod,_nip
dc.l _exit
* mod (s n1 n2 -- mod ) return n1 mod n2
dc.w -1
dc.l link1
link1 set *-4
dc.b $83,'mo',$80!'d'
cnop 0,2
_mod dc.l nest
dc.l _divide_mod,_drop
dc.l _exit
* */mod (s n1 n2 -- rem quot ) internally kept to double
dc.w -1
dc.l link2
link2 set *-4
dc.b $85,'*/mo',$80!'d'
cnop 0,2
_times_divide_mod dc.l nest
dc.l _to_r,_times_d,_r_from,_m_divide_mod
dc.l _exit
* */ (s n1 n2 -- quot )
dc.w -1
dc.l link2
link2 set *-4
dc.b $82,'*',$80!'/'
cnop 0,2
_times_divide dc.l nest
dc.l _times_divide_mod,_nip
dc.l _exit